<?php
/**
 *      [迷你云] (C)2009-2012 南京恒为网络科技.
 *   软件仅供研究与学习使用，如需商用，请访问www.miniyun.cn获得授权
 * 
 */
?>
<?php


class MUtils
{
	
	const LEN_TIME      = 14;

	public static function random_string($length = 40){
		static $str = "abcdefghijklmnopqrstuvwxyz0123456789";
		$rand= "";
		if ($length > MUtils::LEN_TIME)
		$length -= MUtils::LEN_TIME;

		for($i=0; $i<$length; $i++) {
			$rand.= $str[mt_rand() % strlen($str)];
		}

				$t = microtime(true)*10000;
		$rand.=$t;
		return $rand;
	}

	
	public static function convertBytes($val) {
		$val = trim($val);
		$last = strtolower($val[strlen($val)-1]);
		switch($last) {
						case 'g':
				$val *= 1024;
			case 'm':
				$val *= 1024;
			case 'k':
				$val *= 1024;
		}
			
		return $val;
	}

	
	public static function getDeviceUUID($device_info, $device_type, $device_name, $user_id) {
		return md5("{$user_id}_{$device_type}_{$device_info}_{$device_name}_RGeavfnK8GMjBjDQ");
	}

	
	public static function getCurrentTime() {
		$datetime = date("Y-m-d H:i:s");
		return $datetime;
	}

	
	public static function StandResult($success, $msg, $signature = "0") {
		$json = "";
		if ($signature == null || $signature == "0") {
			$json = array (
                "status" => $success,
                "msg" => $msg,

			);
		} else {
			$json = array (
                "status" => $success,
                "msg" => $msg,
                "signature" => $signature,

			);
		}

		echo json_encode($json);
	}

	
	public static function MkDirs($dir, $mode = 0777, $recursive = true) {
		if (is_null($dir) || $dir == "") {
			return false;
		}
		if (is_dir($dir) || $dir == "/") {
			return true;
		}
		if (MUtils::MkDirs(dirname($dir), $mode, $recursive)) {
			return mkdir($dir, $mode);
		}
		return false;
	}

	
	public static function RemoveFile($file_name) {
		if (strlen($file_name) == 0) {
			return false;
		}
		if (strpos($file_name, BASE) === false) {
			return false;
		}
		if (file_exists($file_name) == false) {
			return false;
		}

		if (unlink($file_name) == false) {
			return false;
		}
				$dir = dirname($file_name);
		if (strpos($dir, BASE) === false) {
			return false;
		}

		if (is_dir($dir) == false) {
			return false;
		}
		$dh = opendir($dir);
		$nil = '';
		while ($file = readdir($dh)) {
			$nil .= $file;
		}
		if ($nil == "...") {
			closedir($dh);
			if (rmdir($dir)) {
				return true;
			} else {
				return false;
			}
		}
		return true;
	}

	
	public static function Move($src, $dist) {
		if (strlen($src) == 0 || strlen($dist) == 0) {
			return false;
		}
				if (is_bool(strpos($src, BASE )) || is_bool(strpos($dist, BASE))) {
			return false;
		}
		$flag = 1;
		exec("mv $src $dist",$retval,$flag);
		if ($flag == 1) {
			return false;
		}
		return true;
	}

	
	public static function create($root, $post, $file, $is_need_check_signature=false) {
		FXP::trace(FXP::t('Begin to process {class}::{function}',
		array('{class}'=>"MUtils", '{function}'=>__FUNCTION__)));
		ob_start();
		ob_end_clean();
		$key = $post["key"];
		$file_name = $post["Filename"];
				if ($file["file"]["error"] > 0) {
			FXP::log(FXP::t("Request is Error, file:'{$file["file"]["error"]}'"), MLogger::LEVEL_ERROR);
			return false;
		}
				if (strlen(trim($key)) <= 0 || strlen(trim($file_name)) <= 0) {
			FXP::log(FXP::t("Request is Error, file_name:'{$file_name}'"), MLogger::LEVEL_ERROR);
			return false;
		}
				if (is_bool(strpos(trim($key), "/")) || is_bool(strpos(trim($key), "\${filename}"))) {
			FXP::log(FXP::t("Request is Error, file_name:'{$file_name}'"), MLogger::LEVEL_ERROR);
			return false;
		}

				$path = $root . str_replace("\${filename}", $file_name, $key);

				if (file_exists($path)) {
			return true;
		}
				$dir = dirname($path);
		if (file_exists($dir) == false) {
			$dirname = dirname($path);
			MUtils::MkDirs($dirname);
		}

				move_uploaded_file($file["file"]["tmp_name"], $path);
								if ($is_need_check_signature) {
			if (MUtils::checkSignature($path, PYTHON_PATH, $file_name) == false) {
				MUtils::RemoveFile($path);
				FXP::log(FXP::t("signature is not same , file_name:'{$file_name}'"), MLogger::LEVEL_ERROR);
				return false;
			}
		}

		FXP::trace(FXP::t('end to process {class}::{function}',
		array('{class}'=>"MUtils", '{function}'=>__FUNCTION__)));
		return true;
	}

	
	public static function output($path, $content_type, $output_name) {
								if (headers_sent()) {
			exit;
		}
								$contents = explode("/", $content_type);
								if (strlen(trim($output_name)) <= 0) {
			$output_name = md5(date("Y-m-d G:i:s")); 		}

		$encoded_filename = urlencode($output_name);
		$encoded_filename = str_replace("+", "%20", $encoded_filename);

		$ua = isset($_SERVER ["HTTP_USER_AGENT"]) ? $_SERVER ["HTTP_USER_AGENT"] : NULL;
		header("Cache-Control:");
		header("Cache-Control: public");
		header("Content-Type: " . $content_type);
		if (strcmp($contents[0], 'image') != 0) {
			if (preg_match("/MSIE/", $ua)) {
				header('Content-Disposition: attachment; filename="' . $encoded_filename . '"');
	        } elseif (preg_match ( "/Firefox\/8.0/", $ua )){
                header ( 'Content-Disposition: attachment; filename="' . $file_name . '"' );
			}
			elseif (preg_match("/Firefox/", $ua)) {
				header('Content-Disposition: attachment; filename*="utf8\'\'' . $output_name . '"');
			} else {
				header('Content-Disposition: attachment; filename="' . $output_name . '"');
			}
		}
		header("Accept-Ranges: none");
		header("Content-Length: " . filesize($path));
		header("X-LIGHTTPD-send-file: " . $path);
		exit;
	}

	
	public static function output_ranges($path, $output_name, $content_type) {
								if (headers_sent()) {
			exit;
		}
		$size = filesize($path);
				$seek_start = 0;
		$seek_range = substr($_SERVER['HTTP_RANGE'], 6);
		$range = explode('-', $seek_range);

								if ($range[0] > 0) {
			$seek_start = floatval($range[0]);
		}
		if ($range[1] > 0) {
			$seek_end = floatval($range[1]);
		}
		$length = $seek_end - $seek_start;

								if (strlen(trim($output_name)) <= 0) {
			$output_name = md5(date("Y-m-d G:i:s")); 		}
								$contents = explode("/", $content_type);

								$encoded_filename = urlencode($output_name);
		$encoded_filename = str_replace("+", "%20", $output_name);
		$ua = isset($_SERVER ["HTTP_USER_AGENT"]) ? $_SERVER ["HTTP_USER_AGENT"] : NULL;

		header("HTTP/1.1 206 Partial Content");
		header("Content-Range: bytes $seek_start-$seek_end/$size");
		header("Cache-Control:");
		header('Cache-Control: public');
				header('Content-Type: ' . $content_type);
		if (strcmp($contents[0], 'image') != 0) {
			if (preg_match("/MSIE/", $ua)) {
				header('Content-Disposition: attachment; filename="' . $encoded_filename . '"');
	        } elseif (preg_match ( "/Firefox\/8.0/", $ua )){
            header ( 'Content-Disposition: attachment; filename="' . $file_name . '"' );
			}
			elseif (preg_match("/Firefox/", $ua)) {
				header('Content-Disposition: attachment; filename*="utf8\'\'' . $output_name . '"');
			} else {
				header('Content-Disposition: attachment; filename="' . $output_name . '"');
			}
		}
		header("Accept-Ranges: bytes");
		header("Content-Length: " . $length); 
								$python = PYTHON_PATH;
		$read_path = dirname(__FILE__) . "/../py/readfile.py";
		$str = "$python $read_path $path $seek_start $length";
		FXP::trace($str);
		$descriptorspec = array(
		0 => array("pipe", "r"),  		1 => array("pipe", "w"),  		2 => array("file", "/tmp/error-output.log", "a") 		);
		$process = proc_open("$python $read_path $path $seek_start $length", $descriptorspec, $pipes);

		if (is_resource($process)) {
												
			fwrite($pipes[0], 'hello world');
			fclose($pipes[0]);

			set_time_limit(0);
			echo stream_get_contents($pipes[1]);
			fclose($pipes[1]);
			flush();
			ob_flush();

									$return_value = proc_close($process);
			if ($return_value != 0) {
				header("HTTP/1.1 500 Internal Server Error");
			}
		}
		exit;
	}

	
	public static function download($path, $content_type, $output_name) {
								if (isset ($_SERVER['HTTP_RANGE'])) {
			MUtils::output_ranges($path, $content_type, $output_name);
		} else {
			MUtils::output($path, $content_type, $output_name);
		}
	}

	
	public static function getSignature($path,$python) {
		$sig_path = dirname(__FILE__) . "/../py/signature.py";
		$sig_cal  = "0";
		$res      = array ();
		$rc       = 0;
		exec($python . " " . $sig_path ." " . $path, $res, $rc);
								if ($rc != 1) {
			return $sig_cal;
		}

		if (is_null($res[0])) {
			return $sig_cal;
		}
		$sig_cal = $res[0];
		return $sig_cal;
	}

	
	public static function checkSignature($path,$python,$signature) {
								$retval = MUtils::getSignature($path,$python);
		if (strcmp($retval, $signature) != 0) {
			return false;
		}
		return true;
	}

	
	public static function getPost($file_signature, $offset=0) {
		$key               = substr($file_signature,0,2)."/".substr($file_signature,2,2);
		$key              .= "/".substr($file_signature,4,2)."/".substr($file_signature,6,2);

								$input = array( "Filename" => "{$file_signature}",
                        "key" => "$key/\${filename}");
								$output = MUtils::getRequesSignature($input);
		$expiration_time   = $output["expiration_date"];
		$digital_signature = $output["digital_signature"];

		$post = array();
		$post["Filename"]               = $file_signature;
		$post["AWSAccessKeyId"]         = MConst::ACCESS_KEY_ID;
		$post["key"]                    = $file_signature;
		$post["expiration_date"]        = $expiration_time;
		$post["digital_signature"]      = $digital_signature;
		$post["offset"]                 = $offset;
		$post["success_action_status"]  = "201";

		$post["acl"]                    = "";
		$post["signature"]              = "";
		$post["policy"]                 = "";
		$post = json_encode($post);
		return $post;
	}

	
	public static function getRequesSignature($input, $expire=21600) {
		if (is_array($input) == false) {
			return  false;
		}
				$expired_date = time() + $expire;
								$new_input = array();
		foreach ($input as $key=>$value) {
						$key = strtolower($key);
			$new_input[$key] = $value;
		}
								$keys = array_keys($new_input);
								natsort($keys);
								$str = "";
		foreach ($keys as $key) {
			$str .= $key . $new_input[$key];
		}
		$str .= MConst::EXPIRATION_DATE . $expired_date;
		$signature = MUtils::getSha1Signature($str);
								$input["expiration_date"] = $expired_date;
		$input["digital_signature"] = $signature;
		return $input;
	}

	
	public static function getSha1Signature($str) {
		$str .= MConst::ACCESS_KEY;
		return SHA1($str);
	}

	
	public static function buildStatus($status, $code, $success, $msg) {
				if ($status == null) {
			$status = new Status();
		}
		$status->set_code($code);
		$status->set_success($success);
		$status->set_msg($msg);
		return $status;
	}

	
	public static function getFileSha256($file) {
		return hash_file('sha256', $file);
	}

	
	public static function getFileSha1($file) {
		return hash_file('sha1', $file);
	}
	
	public static function getStrSha256($str) {
		return hash('sha256', $str);
	}
    
    public static function getStrSha1($str) {
        return hash('sha1', $str);
    }
	
	public static function getPathBySplitStr($str) {
								$parts = str_split(substr($str,0,8), 2);

		$path = join("/", $parts);
		$path = $path . "/" . $str;
		return $path;
	}

	
	public static function getConflictName($name, $names=array()) {
										$index = 1;
		$paths = pathinfo($name);
		$file_name = $paths["filename"];
		$extension = $paths["extension"];

		$tmp_name = strtolower($name);

		while (isset($names[$tmp_name])) {
			$tmp_name = $file_name . "($index)";
			if ($extension) {
                $tmp_name .= ".$extension";
            } 
			$index += 1;
												if ($index == 50) {
				break;
			}
		}

		$file_name = $tmp_name;
		FXP::trace("function: '{__FUNCTION__}',conflict_name:'{$file_name}'");
		return $file_name;
	}

	
	public static function getFileVersions($version_id, $action, $user_id, $user_nick,$versions="a:0:{}") {
		$versions = is_null($versions)||empty($versions) ? "a:0:{}" : $versions;
		$version               = array();
		$version["type"]       = $action;
		$version["version_id"] = $version_id;
		$version["user_id"]    = $user_id;
		$version["user_nick"]  = $user_nick;
		$version["datetime"]   = MUtils::getCurrentTime();
		$versions              = unserialize($versions);
		array_push($versions, $version);
		return serialize($versions);
	}

	
	public static function getSizeByLocale($locale, $size) {
		$retval = "$size bytes";
		if ($locale === "KB" || $locale === "kb") {
			$tmp = $size / 1024.0;
			$tmp = number_format($tmp, 2);
			$retval = "$tmp$locale";
		} elseif ($locale === "mb" || $locale === "MB" || $locale === "M") {
			$divisor = 1048576.0;
			$tmp = $size / $divisor;
			$tmp = number_format($tmp, 2);
			$retval = "$tmp$locale";
		} elseif ($locale === "GB" || $locale === "gb" || $locale === "G") {
			$divisor = 1073741824.0;
			$tmp = $size / $divisor;
			$tmp = number_format($tmp, 2);
			$retval = "$tmp$locale";
		}
		return $retval;
	}

	
	public static function isExistReversion($rev, $versions) {
		if ($rev == 0) {
			return true;
		}
		$versions = unserialize($versions);
		foreach ($versions as $v) {
			if ($rev == $v["version_id"]) {
				return true;
			}
		}

		return false;
	}

	
	public static function convertStandardPath($path)
	{
		if ($path == "")
		{
			return false;
		}
								$path = str_replace("\\", "/", $path);
		while (!(strpos($path, "//") === false)) {
			$path = str_replace("//", "/", $path);
		}

								if ($path[0] != "/")
		{
			$path = "/".$path;
		}

								$len = strlen($path);
		if ($len > 1 && "/" == $path[$len - 1]) {
			$path = substr($path, 0, $len - 1);
		}

		return $path;
	}

	
	public static function checkNameInvalid($file_name)
	{
		if ($file_name === "")
		{
			return true;
		}
		if ($file_name{strlen($file_name)-1} == ".") {
		    return true;
		}
		return preg_match("/[".preg_quote("^|?*\\<\":>")."]/",$file_name);
	}

	
	public static function convertToBool($value)
	{
		if (is_string ( $value ) === true) {
			if (strtolower ( $value ) === "false") {
				$value = false;
			} elseif (strtolower ( $value ) === "true") {
				$value = true;
			}
		}
		return $value;
	}

	
	public static function formatIntTime($time, $format="D, d M Y G:i:s O")
	{
		return date($format,$time);
	}

	
	public static function get_basename($filePath)
	{
												$first_index = strrpos($filePath, "/");
		$second_index = strrpos($filePath, "\\");
		$index = $first_index;
		if ($first_index < $second_index)
		{
			$index = $second_index;
		}
		$file_name = substr($filePath, $index+1);
		if ($file_name === false)
		{
			return "";
		}
		return $file_name;
	}
    
	public static function mime_content_type($filename) {

        $mime_types = array(

            'txt'  => 'text/plain',
            'htm'  => 'text/html',
            'html' => 'text/html',
            'php'  => 'text/html',
            'css'  => 'text/css',
            'js'   => 'application/javascript',
            'json' => 'application/json',
            'xml'  => 'application/xml',
            'swf'  => 'application/x-shockwave-flash',
            'flv'  => 'video/x-flv',

                   'bmp'  => 'image/bmp',
           'cod'  => 'image/cis-cod',
           'gif'  => 'image/gif',
           'ief'  => 'image/ief',
           'jpe'  => 'image/jpeg',
           'jpeg' => 'image/jpeg',
           'jpg'  => 'image/jpeg',
           'jfif' => 'image/pipeg',
           'svg'  => 'image/svg+xml',
           'tif'  => 'image/tiff',
           'tiff' => 'image/tiff',
           'ras'  => 'image/x-cmu-raster',
           'cmx'  => 'image/x-cmx',
           'ico'  => 'image/x-icon',
           'png'  => 'image/png',
           'pnm'  => 'image/x-portable-anymap',
           'pbm'  => 'image/x-portable-bitmap',
           'pgm'  => 'image/x-portable-graymap',
           'ppm'  => 'image/x-portable-pixmap',
           'rgb'  => 'image/x-rgb',
           'xbm'  => 'image/x-xbitmap',
           'xpm'  => 'image/x-xpixmap',
           'xwd'  => 'image/x-xwindowdump',
           'svgz' => 'image/svg+xml',

                    'zip' => 'application/zip',
            'rar' => 'application/x-rar-compressed',
            'exe' => 'application/x-msdownload',
            'msi' => 'application/x-msdownload',
            'cab' => 'application/vnd.ms-cab-compressed',


                   'au'   => 'audio/basic',
           'snd'  => 'audio/basic',
           'mid'  => 'audio/mid',
           'rmi'  => 'audio/mid',
           'mp3'  => 'audio/mpeg',
           'aif'  => 'audio/x-aiff',
           'aifc' => 'audio/x-aiff',
           'aiff' => 'audio/x-aiff',
           'm3u'  => 'audio/x-mpegurl',
           'ra'   => 'audio/x-pn-realaudio',
           'ram'  => 'audio/x-pn-realaudio',
           'wav'  => 'audio/x-wav',


                   'mp4'   => 'video/mp4',
           'qt'    => 'video/quicktime',
           'mov'   => 'video/quicktime',
           '3gp'   => 'video/3gpp',
           'wmv'   => 'video/x-ms-wmv',
           'avi'   => 'video/x-msvideo',
           'mp2'   => 'video/mpeg',
           'mpa'   => 'video/mpeg',
           'mpe'   => 'video/mpeg',
           'mpeg'  => 'video/mpeg',
           'mpg'   => 'video/mpeg',
           'mpv2'  => 'video/mpeg',
           'mov'   => 'video/quicktime',
           'qt'    => 'video/quicktime',
           'lsf'   => 'video/x-la-asf',
           'lsx'   => 'video/x-la-asf',
           'asf'   => 'video/x-ms-asf',
           'asr'   => 'video/x-ms-asf',
           'asx'   => 'video/x-ms-asf',
           'avi'   => 'video/x-msvideo',
           'movie' => 'video/x-sgi-movie',
           'rmvb'  => 'video/vnd.rn-realvideo',
           'rm'    => 'video/vnd.rn-realvideo',
           'viv'   => 'video/vnd.vivo',
           'vivo'  => 'video/vnd.vivo',


                    'pdf' => 'application/pdf',
            'psd' => 'image/vnd.adobe.photoshop',
            'ai'  => 'application/postscript',
            'eps' => 'application/postscript',
            'ps'  => 'application/postscript',

                    'doc'  => 'application/msword',
		    'docx' => 'application/msword',
            'rtf'  => 'application/rtf',
            'xls'  => 'application/msexcel',
		    'xlsx' => 'application/msexcel',
            'ppt'  => 'application/mspowerpoint',
		    'pptx' => 'application/mspowerpoint',

                    'odt' => 'application/vnd.oasis.opendocument.text',
            'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
        );
        $ext = explode('.',$filename);
		$ext = strtolower(array_pop($ext));
		if (array_key_exists($ext, $mime_types)) {
			return $mime_types[$ext];
		}
		elseif (function_exists('finfo_open')) {
			$finfo = finfo_open(FILEINFO_MIME);
			$mimetype = finfo_file($finfo, $filename);
			finfo_close($finfo);
			return $mimetype;
		}
		else {
			return 'application/octet-stream';
		}
	}
    
    public static function isExistThumbnail($type, $size) {
        if ($size > MConst::MAX_IMAGE_SIZE || $size <= 0) {
            return false;
        }
        foreach ( MThumbnailBase::$_support_types as $value ) {
            if ($value == $type) {
                return true;
            }
        }
        return false;
    }
    
    
    public static function pathinfo_utf($path) {
        $path = self::convertStandardPath($path);
        $retval = array (
            'dirname' => "",
            'basename' => "", 
            'extension' => "", 
            'filename' => "" 
        );
        if (strpos ( $path, '/' ) !== false) {
            $parts = explode ( '/', $path );
            $basename = end ( $parts );
        }
        
        if (empty ( $basename ))
            return $retval;
        
        $dirname = substr ( $path, 0, strlen ( $path ) - strlen ( $basename ) - 1 );
        
        if (strpos ( $basename, '.' ) !== false) {
            $ext_parts = explode ( '.', $path );
            $extension = end ( $ext_parts );
            $filename = substr ( $basename, 0, strlen ( $basename ) - strlen ( $extension ) - 1 );
        } else {
            $extension = '';
            $filename = $basename;
        }
        
        return array (
            'dirname' => $dirname, 
            'basename' => $basename, 
            'extension' => $extension, 
            'filename' => $filename 
        );
      } 
      
    
    public static function totalSize($user_id){
        $total =  DEFAULT_USER_SPACE *1024*1024;
        $userMeta = MUserMetas::queryMetaByKey($user_id, "space");
        if (!empty($userMeta)){
            $total = intval($userMeta[0]["meta_value"])*1024*1024;
        }
        return $total;
    }
}
?>